﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System
{
    /// <summary>
    /// The <see cref="System.String"/> extensions.
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// The <see cref="string.Trim()"/> method only trims 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x0085, 0x2028, and 0x2029.
        /// This array adds in control characters.
        /// </summary>
        static readonly char[] nonVisiableCharacters = new char[]
        {
            (char)0x00, (char)0x01, (char)0x02, (char)0x03, (char)0x04, (char)0x05,
            (char)0x06, (char)0x07, (char)0x08, (char)0x09, (char)0x0a, (char)0x0b,
            (char)0x0c, (char)0x0d, (char)0x0e, (char)0x0f, (char)0x10, (char)0x11,
            (char)0x12, (char)0x13, (char)0x14, (char)0x15, (char)0x16, (char)0x17,
            (char)0x18, (char)0x19, (char)0x20, (char)0x1a, (char)0x1b, (char)0x1c,
            (char)0x1d, (char)0x1e, (char)0x1f, (char)0x7f, (char)0x85, (char)0x2028, (char)0x2029
        };

        /// <summary>
        /// Format the specified string to OriginalUser id pattern in the database.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The formatted employee identifier.</returns>
        public static string ToOriginalUser(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return value;
            }
            if (value.IndexOf("@") > 0)
            {
                return value.Split('@')[0];
            }
            else if (value.IndexOf("\\") > 0)
            {
                return value.Split('\\')[1];
            }
            else
            {
                throw new Exception("未处理");
            }
        }
        /// <summary>
        /// Hexadecimals to string.
        /// </summary>
        /// <param name="hex">The hexadecimal.</param>
        /// <returns></returns>
        public static string HexToString(this string hex)
        {
            if (string.IsNullOrEmpty(hex))
            {
                return string.Empty;
            }
            string temp = string.Empty;
            byte[] b = new byte[hex.Length / 2];
            for (int i = 0; i < hex.Length / 2; i++)
            {
                temp = hex.Substring(i * 2, 2);
                b[i] = Convert.ToByte(temp, 16);
            }
            return Encoding.Default.GetString(b);
        }

        /// <summary>
        /// Convert  to the <paramref name="value"/> to a safe file name.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static string ToSafeFileName(this string value)
        {
            value = value.Replace("\"", string.Empty);
            string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()) + "?" + "&";
            foreach (char c in invalid)
            {
                value = value.Replace(c.ToString(), "_");
            }
            return value;
        }

        /// <summary>
        /// Determines whether this instance is int32.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="style">The number style.</param>
        /// <returns>
        ///   <c>true</c> if the specified value is int32; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsInt32(this string value, NumberStyles style = NumberStyles.None)
        {
            try
            {
                int.Parse(value, style);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// Determines whether this instance is int64.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="style">The number style.</param>
        /// <returns>
        ///   <c>true</c> if the specified value is int64; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsInt64(this string value, NumberStyles style = NumberStyles.None)
        {
            try
            {
                int.Parse(value, style);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        //public static bool IsNullOrBlank(this string value)
        //{
        //    if (value == null || string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value))
        //    {
        //        return true;
        //    }
        //    if (value.Trim(nonVisiableCharacters).Length == 0)
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        /// <summary>
        /// Removes all leading and trailing non visible characters from the current System.String object.
        /// </summary>
        /// <param name="value">The string to test.</param>
        /// <returns>
        /// The string that remains after all non visible characters are removed from the
        /// start and end of the current string. If no characters can be trimmed from the
        /// current instance, the method returns the current instance unchanged.
        ///</returns>
        public static string TrimBlank(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }
            else
            {
                return value.Trim(nonVisiableCharacters);
            }
        }
        /// <summary>
        /// Convert specified string to an <see cref="Enum"/> value.
        /// </summary>
        /// <typeparam name="T">The type of enum.</typeparam>
        /// <param name="value">The string to test.</param>
        /// <param name="ignoreCase">true to ignore case during the comparison; otherwise, false.</param>
        /// <exception cref="ArgumentException"></exception>
        /// <returns>The converted <see cref="Enum"/> value.</returns>
        //public static T ToEnum<T>(this string value, bool ignoreCase = true)
        //{
        //    if (value.IsNullOrBlank())
        //    {
        //        throw new ArgumentException("Must specify valid information for parsing in the string.", nameof(value));
        //    }
        //    Type t = typeof(T);
        //    if (!t.IsEnum)
        //    {
        //        throw new ArgumentException("Type provided must be an Enum.", "T");
        //    }
        //    return (T)Enum.Parse(t, value, ignoreCase);
        //}

        /// <summary>
        /// 日期格式化成固定的字符串日期格式
        /// 2019-06-27 01:00
        /// </summary>
        /// <param name="dt">时间</param>
        /// <param name="formatStr">字符串格式化，可空</param>
        /// <returns>格式化后的日期字符串</returns>
        public static string ToHSString(this DateTime dt, string formatStr = null)
        {
            var str = dt.ToString("yyyy-MM-dd HH:mm");
            if (!string.IsNullOrEmpty(formatStr))
                str = dt.ToString(formatStr);
            return str;
        }


        /// <summary>
        /// MD5，32位加密
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToMD5_32(this string value)
        {
            byte[] b = System.Text.Encoding.Default.GetBytes(value);
            b = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(b);
            string ret = "";
            for (int i = 0; i < b.Length; i++)
            {
                ret += b[i].ToString("x").PadLeft(2, '0');
            }
            return ret;
        }
    }
}

